#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <iostream>

using namespace std;

int main()
{
	//create socket
	int fd = socket(AF_INET, SOCK_STREAM, 0);
	if(fd == -1)
	{
		perror("socket\n");
		exit(-1);
	}
	printf("socket fd=%d\n",fd);

	//build connection address
	struct sockaddr_in addr;
	bzero(&addr, sizeof(struct sockaddr_in));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(50001);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	
	//data connect address
	struct sockaddr_in data_addr;
	bzero(&data_addr, sizeof(struct sockaddr_in));
	data_addr.sin_family = AF_INET;
	data_addr.sin_port = htons(8001);
	data_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

	//connect to data serial server
	struct timeval timeout = {5, 0};

	int res;
	res = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
	if(res == -1)
	{
		perror("bind");
		close(fd);
		exit(-1);
	}
	printf("%d\n", ntohs(addr.sin_port));
	printf("bind address successful!\n");

	//accept or send message
	char buf[65536];
	pid_t pid;
	listen(fd, 5);
	while(true)
	{
		struct sockaddr_in cliaddr;
		socklen_t clilen = sizeof(cliaddr);
		int connfd = accept(fd, (struct sockaddr *)&cliaddr, &clilen);
		printf("connfd:%d\n", connfd);
		bzero(buf, sizeof(buf));
		res = recv(connfd, buf, sizeof(buf), 0);
		if(res > 0)
		{
			//printf("recv len: %d\n", res);
			/*
			for(int i = 0; i < res; i++)
				printf("\\x%02x ", buf[i]);
			cout<<endl;
			*/
			uint16_t p_len;	//package length
			p_len = buf[0] * 256 + buf[1];
			//memcpy(&p_len, buf, 2);
			//cout<<"p_len: "<<p_len<<endl;

			int8_t p_type;	//package tpye 0:command 1:data
			memcpy(&p_type, buf + 2, 1);
			//cout<<"p_type:"<<int(buf[2])<<endl;
			//printf("p_type: %x \n", p_type);
			if(p_type == 0)
			{
				cout<<"receive command"<<endl;
				char cmd[100];
				memcpy(cmd, buf + 3, p_len - 3);
				printf("receive cmd :|%s|\n", cmd);
				char rep[100];
				int rep_len = sprintf(rep, "%s ok!", cmd);
				cout<<"send rep: "<<rep<<endl;
				send(connfd, rep, rep_len, 0);
			}//end if(p_type == 0)
			else if(p_type == 1)
			{
				int data_conn = socket(AF_INET, SOCK_STREAM, 0);
				setsockopt(data_conn, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
				connect(data_conn, (struct sockaddr *)&data_addr, sizeof(data_addr));
				char temp[65535];
				int len = 0;
				/*
				cout<<"data:"<<endl;
				for(int i = 13; i < p_len; i++)
					printf("\\x%02x ", char(buf[i]));
				printf("\n");
				*/
				send(data_conn, buf + 13, p_len - 13, 0);
				cout<<"send device command to serial"<<endl;
				while(true)
				{
					bzero(temp, sizeof(temp));
					int serial_len = recv(data_conn, temp, sizeof(temp), 0);
					if(serial_len == -1)
						perror("recv from local error");
					res = send(connfd, temp, serial_len, 0);
					cout<<"recv from serial and send to server len:"<<serial_len<<endl;
					if(serial_len == -1)
						break;
				}
				close(data_conn);
			}//end else if(p_type == 1)
		}//end if(r>0)
		close(connfd);
	}//end while(true)
	close(fd); //close listen fd
	return 0;
}//end main
